import TreeBaseStore, { TreeBaseStoreProps } from './treeBaseStore';
import { action, toJS, observable } from 'mobx';
import { WeaLocaleProvider } from 'ecCom';
import * as API_TREE from '../../apis/tree';
import window, { replaceE8Url } from '../../util';
import { message, Modal } from 'antd';
import _ from 'lodash';
import { isFromProtal } from '../../util/cubeUtil';

const getLabel = WeaLocaleProvider.getLabel;

export interface TreeStoreProps extends TreeBaseStoreProps {
    init: Function;
    changeLoading: Function;
    onLoadRight: Function;
    reloadSearch: Function;
    getTreeData: Function;
    getTreeHref: (params: {pid: string, id?: string, isRefreshTree?: string},hrmtype?:string) => void;
    quickSearch: (search: string) => void;
    onExpandChange: (expandKey: string[]) => void;
    tree?: TreeStore;
    url?: string;
    mainFrameRefVisible: boolean;
    remarkRefVisible: boolean;
    currentNodeData?:any;
    onChangeTree:(tree: string[]) => void;
    currentTree:string;
    combintreeway:any;
    combintree:any;
    displaywidth:number;
    defaulthideleft:any;
    showLeft?;
    setShowLeft?;
    setDefaultHideLeft?;
}

export class TreeStore extends TreeBaseStore implements TreeStoreProps {
    tree?: TreeStore = undefined;
    url?: string = '';
    @observable mainFrameRefVisible: boolean = false;
    @observable remarkRefVisible: boolean = false;
    @observable currentNodeData?:any;
    @observable combintreeinfo?:any;
    treeDatas: any = [];
    @observable showLeft?: boolean;
    @observable defaultHideLeft: boolean = false;

    constructor() {
        super();

    }

    onChangeTree = (treeid)=>{
        if(this.combintreeinfo&&this.combintreeinfo[treeid]){
            this.update(this.combintreeinfo[treeid]);
            const defaultAdress=this.combintreeinfo[treeid].defaultAdress
            this.isCube = false;
            this.url='';
            if (defaultAdress) {
                this.onLoadRight({href:defaultAdress});
            }else{
                this.remarkRefVisible = true;
                this.mainFrameRefVisible = false;
            }
        }
        this.currentTree=treeid;
        this.expandKeys = [];
        this.datas=[];
        this.params['id']=treeid;
        this.getTreeData({...this.params}, true, (datas) => {
            if (this.expandFirstNode > 0 && datas && datas.length > 0) {
                this.getTreeDataRecursion({ pid: datas[0].domid }, this.expandFirstNode);
                this.expandKeys.push(datas[0].domid);
            }
        });
    }

    refreshTree = (id) => {
        let pid = this.getPid(this.datas, id);
        if(!pid)return;
        this.getTreeData({ pid }, false, (datas) => {
            if (this.expandKeys.indexOf(id) >= 0) {
                this.getTreeData({ pid: id }, false);
            }
        })
    }
    getPid = (datas: any[], id: string, pid = '0_0') => {
        let rs = false;
        for (let d of datas) {
            if (d.key == id) {
                return pid;
            } else if (d.childs) {
                let rs = this.getPid(d.childs.slice(), id, d.domid);
                if (rs) {
                    return rs;
                }
            }
        }
        return rs;
    }
    @action
    init = (params, callback?: Function) => {
        window.refreshTree = this.refreshTree;
        this.params = params;
        if (params.treehavekeyword && params.treehavekeyword == 'false') {
            Modal.error({
                title: '提示',
                content: getLabel('389773', "树对应的查询列表未设置关键字，请先设置关键字"),
                onOk() {
                },
            });
        }
        API_TREE.initTree(params).then(({ status, error, ...props }) => {
            if(isFromProtal()){
                delete props.windowTitle
            }
            if (status == '1') {
                this.update(props);
                this.initLeftTreeShow();
            } else {
                message.error(error);
                throw error;
            }
            callback && callback();
            if(props.combintree&&props.combintree.length>0){
                this.currentTree=props.combintree[0].companyid;
            }
            this.getTreeData(params, true, (datas,hideroot) => {
                if (this.expandFirstNode > 0 && datas && datas.length > 0) {
                    if(hideroot){
                        datas.forEach(e => {
                            if (e.haschild) {
                                let hrmparm={};
                                if(e.hrmtype){
                                    hrmparm['hrmtype']=e.hrmtype;
                                }
                                this.getTreeDataRecursion({ pid: e.domid,...hrmparm }, this.expandFirstNode);
                                this.expandKeys.push(e.domid);
                            }
                        });
                    }else{
                        this.getTreeDataRecursion({ pid: datas[0].domid }, this.expandFirstNode);
                        this.expandKeys.push(datas[0].domid);
                    }
                }
            });
        });
    }

    @observable selectedNodeKeys  = [] as string[];

    selectedLoadding = false as boolean;
    /**
     *  遍历datas找到对应得domid
     */
    getDomid = (datas, selectNode)=>{

        for(let i=0; i<datas.length; i++){

            const data = datas[i];

            if(data.key == selectNode){
                return data;
            }

            if(data.haschild && data.childs) {

                const d = this.getDomid(data.childs, selectNode);

                if(d != null) return d;
            }
        }
        
        return null;
    }

    /**
     * 加载展开节点数据
     */
    getSelectTreeDatas = (params) => {

        const pids = this.getPids(params);
        API_TREE.getTreeDatas({ ...this.params, ...params }).then(({ status, error, datas, ...props }) => {
            if (status == '1') {
                this.update(props);
                this.treeDatas = datas;
                datas = this.addParentId2Node(pids, datas);
                this.updateTreeDatas(params, datas);
            } else {
                message.error(error);
                throw error;
            }
        })
    }

    /**
     *  根据展开级数，递归查询
     */

    getTreeDataRecursion = (params, expandFirstNode: number) => {
        expandFirstNode--;
        const pids = this.getPids(params);
        API_TREE.getTreeDatas({ ...this.params, ...params }).then(({ status, error, datas,maxid, ...props }) => {
            if (status == '1') {
                this.update(props);
                this.treeDatas = datas;
                datas = this.addParentId2Node(pids, datas);
                this.updateTreeDatas(params, datas);
                if (expandFirstNode > 0) {
                    datas.forEach(e => {
                        if (e.haschild) {
                            let hrmparm={};
                            if(e.hrmtype){
                                hrmparm['hrmtype']=e.hrmtype;
                            }
                            this.getTreeDataRecursion({ pid: e.domid,...hrmparm }, expandFirstNode);
                            this.expandKeys.push(e.domid);
                        }
                    });
                }

                //已经展开完毕
                if(expandFirstNode <= 0 && !this.selectedLoadding) {

                    // 设置为加载选中节点状态, 防止多次加载
                    this.selectedLoadding = true;

                    // 根据连接地址中得参数，选中对应节点
                    if(maxid) {
                      const selectNode = maxid;
                      const newthis = this;
                      setTimeout(function() {
                          
                        // 遍历this.datas 找到domid
                        const data = newthis.getDomid(newthis.datas, selectNode);
                        if(data != null) {

                            const domId = data.domid;

                            // 选中
                            newthis.selectedNodeKeys.push(domId);

                            // 展开
                            if(newthis.expandKeys.indexOf(domId) == -1) {
                                newthis.expandKeys.push(domId);
                            }

                            // 加载展开下级数据
                            if(data.haschild && !data.childs ) {
                                let hrmparm = {};
                                if (data.hrmtype) {
                                    hrmparm['hrmtype'] = data.hrmtype;
                                }
                                newthis.getSelectTreeDatas({ pid: domId, ...hrmparm });
                            }

                            // 加载选中节点右侧连接
                            newthis.getTreeHref({pid: domId});
                        }
                      },1000) 
                    }
                }
            } else {
                message.error(error);
                throw error;
            }
        })
    }

    getParentInfo = (datas: any[], pid, key: string) => {
        let rs = false;
        for (let d of datas) {
            if (d.domid == pid) {
                return d[key];
            } else if (d.childs) {
                let rs = this.getParentInfo(d.childs.slice(), pid, key);
                if (rs) {
                    return rs;
                }
            }
        }
        return rs;
    }

    getPids = ({ pid }) => {
        let pids = this.getParentInfo(this.datas, pid, "pids");
        if (!pids) {
            pids = "";
        } else {
            pids += ",";
        }
        if (pid && pid.length > 33 && pid.charAt(32) == '_') {//有uuid前缀
            pid = pid.substring(pid.indexOf("_") + 1);
        }
        pids += pid;
        return pids;
    }

    @action
    getTreeData = (params, init?: boolean, callback?: Function) => {
        let hrmparam={};
        if(this.currentNodeData&&this.currentNodeData.data&&this.currentNodeData.data.hrmtype){
            hrmparam['hrmtype']=this.currentNodeData.data.hrmtype;
        }
        const pids = this.getPids(params);
        API_TREE.getTreeDatas({ ...this.params, ...params,...hrmparam }).then(({ status, error, datas,hideroot, ...props }) => {
            callback && callback(datas,hideroot)
            if (status == '1') {
                this.update(props);
                this.treeDatas = datas;
                if (init) {
                    this.datas = datas;
                } else {
                    datas = this.addParentId2Node(pids, datas);
                    this.updateTreeDatas(params, datas);
                }
            } else {
                message.error(error);
                throw error;
            }
            this.isInit = true;
        })
    }

    @action
    setDefaultHideLeft = (bool: boolean) => {
        this.defaultHideLeft = bool;
    };
    @action
    setShowLeft = (bool: boolean) => {
        this.showLeft = bool;
    };

    @action
    initLeftTreeShow = () => {
        if (this.defaultHideLeft) {
            return this.setShowLeft(false);
        } else {
            if (this.defaulthideleft && this.defaulthideleft == '1' && this.showLeft == undefined) {
                return this.setShowLeft(false);
            }
        }
        this.setShowLeft(true);
    }
    @action
    getTreeHref = (params: {pid: string, id?: string, isRefreshTree?: string},hrmtype?:string) => {
        let hrmparam={}
        if(hrmtype){
            hrmparam={hrmtype:hrmtype}
        }
        API_TREE.getTreeHref({
            ...this.params, ...params,
            isRefreshTree: this.isRefreshTree, ...hrmparam
        }).then(({ status, error, href, ...props }) => {
            if (status == '1') {
                href = this.getRealHref(params.pid, href);
                let beginindex = href.indexOf("$");
                while (beginindex > -1) {
                    let endindex = href.indexOf("$", beginindex + 1);
                    let subDress = href.substring(beginindex + 1, endindex);
                    if (endindex > -1) {
                        if (this.params && this.params[subDress]) {
                            href = href.replace('$' + subDress + '$', this.params[subDress]);
                        } else {
                            href = href.replace('$' + subDress + '$', '');
                        }
                    } else {
                        break;
                    }
                    beginindex = href.indexOf("$");
                }
                this.update(props);
                if (href != '') {
                    this.onLoadRight({ href });
                }
            } else {
                message.error(error);
                throw error;
            }
        })
    }

    getRealHref = (id: any, href: any) => {
        if (href.indexOf("$") < 0 || id.indexOf("_") < 0) {
            return href;
        }
        const lowerHref = href.toLowerCase();
        if (lowerHref.indexOf("$treenodeid_id$") > -1) {//树节点id
            let treenodeid = id.substring(0, id.lastIndexOf("_"));
            if (id.length > 33 && id.charAt(32) == '_') {//有uuid前缀
                treenodeid = id.substring(id.indexOf("_") + 1);
            }
            href = href.replace(new RegExp("\\$treenodeid_id\\$", "gi"), treenodeid);
        }

        if (lowerHref.indexOf("$treenodeid$") > -1) {//树节点id
            let treenodeid = id.substring(0, id.lastIndexOf("_"));
            if (id.length > 33 && id.charAt(32) == '_') {//有uuid前缀
                treenodeid = id.substring(id.indexOf("_") + 1, id.lastIndexOf("_"));
            }
            href = href.replace(new RegExp("\\$treenodeid\\$", "gi"), treenodeid);
        }

        if (lowerHref.indexOf("$superiorkey$") > -1) {//直接上级节点的主键值
            let parentPkId = this.getParentInfo(this.datas, id, "pids");
            const parentPkIdArr = parentPkId.split(",");
            if (parentPkIdArr.length > 0) {
                parentPkId = parentPkIdArr[parentPkIdArr.length - 1];
            }
            if (parentPkId.indexOf("_") > -1) {
                parentPkId = parentPkId.substring(parentPkId.lastIndexOf("_") + 1);
            }
            href = href.replace(new RegExp("\\$superiorkey\\$", "gi"), parentPkId);
        }

        if (lowerHref.indexOf("$treenodeid_superiorkey$") > -1) {
            let parentPkId = this.getParentInfo(this.datas, id, "pids");
            const parentPkIdArr = parentPkId.split(",");
            if (parentPkIdArr.length > 0) {
                parentPkId = parentPkIdArr[parentPkIdArr.length - 1];
            }
            href = href.replace(new RegExp("\\$treenodeid_superiorkey\\$", "gi"), parentPkId);
        }

        if (lowerHref.indexOf("$allsuperiorkey$") > -1) {//所有上级节点的主键值
            const pids = this.getParentInfo(this.datas, id, "pids");
            const pidArr = pids.split(",");
            let pkIds = "";
            for (let pid of pidArr) {
                pkIds += "," + pid.substring(pid.indexOf("_") + 1);
            }
            if (pkIds.length > 0) {
                pkIds = pkIds.substring(1);
            }
            href = href.replace(new RegExp("\\$allsuperiorkey\\$", "gi"), pkIds);
        }

        if (lowerHref.indexOf("$treenodeid_allsuperiorkey$") > -1) {
            const pids = this.getParentInfo(this.datas, id, "pids");
            const pidArr = pids.split(",");
            let pkIds = "";
            for (let pid of pidArr) {
                pkIds += "," + pid;
            }
            if (pkIds.length > 0) {
                pkIds = pkIds.substring(1);
            }
            href = href.replace(new RegExp("\\$treenodeid_allsuperiorkey\\$", "gi"), pkIds);
        }

        let count = 10;
        while (href.toLowerCase().indexOf("superiorkey") > -1 && count > 0) {
            count--;
            let suplevel = 1;
            let isNeedNodeId = false;
            let superiorkey = href.substring(href.toLowerCase().indexOf("superiorkey"));
            if (href.toLowerCase().indexOf("$superiorkey") > -1) {//不包含树节点id
                superiorkey = href.substring(href.toLowerCase().indexOf("$superiorkey") + 1);
            } else {//包含树节点id
                isNeedNodeId = true;
                superiorkey = href.substring(href.toLowerCase().indexOf("$treenodeid_superiorkey") + 1);
            }

            superiorkey = superiorkey.substring(0, superiorkey.indexOf("$"));
            suplevel = suplevel + this.getCount(superiorkey, "_key");

            const pids = this.getParentInfo(this.datas, id, "pids");
            const pidArr = pids.split(",");
            let pkIds = "";
            if (pidArr.length < suplevel) {
                pkIds = "";
                if (!!((window as any).console && (window as any).console.log)) {
                    (window as any).console.log("pids获取失败:", pids);
                }
            }
            pkIds = pidArr[pidArr.length - suplevel];
            if (!isNeedNodeId) {
                pkIds = pkIds.substring(pkIds.lastIndexOf("_") + 1);
            }
            href = href.replace(new RegExp("\\$" + superiorkey + "\\$", "gi"), pkIds);
        }
        href = this.getUrlParams(href);
        return href;
    }

    getUrlParams = (href) => {
        for (let key in this.params) {
            if (key == "id" || key == "_key" || key == "guid" || href.indexOf("?" + key + "=") > -1 || href.indexOf("&" + key + "=") > -1) {
                continue;
            }
            if (href.indexOf("?") > -1) {
                href += "&";
            } else {
                href += "?";
            }
            href += key;
        }
        return href;
    }

    getCount = (str, r) => {
        r = eval("/" + r + "/ig")
        return str.match(r) ? str.match(r).length : 0;
    }

    @action
    quickSearch = (search: string) => {
        const urlParams:any = this.parseUrlParams();
        const _id = (this.params as any).id;
        if (search || (_id&&_id!==urlParams.id)) { // 平铺展示时，search为空仍需调用quickSearch接口
            API_TREE.quickSearch({ ...this.params, search }).then(({ status, error, datas, expandKeys }) => {
                if (status == '1') {
                    this.datas = datas;
                    this.expandKeys = expandKeys;
                } else {
                    message.error(error);
                    throw error;
                }
            })
        } else {
            this.expandKeys = [];
            this.init(this.params);
        }
    }
    parseUrlParams = () => {
        const urlHash = location.hash.split('?')[1];
        let urlParams = {};
        if (urlHash) {
            let paramsArr = urlHash.split('&');
            for (let i=0,len=paramsArr.length; i<len; i++) {
                let item = paramsArr[i].split('=');
                urlParams[item[0]] = item[1];
            }
        }
        return urlParams;
    }
    @action
    reloadSearch = (params, callback = () => {
        if (this.defaultAdress) {
            let beginindex = this.defaultAdress.indexOf("$");
            while (beginindex > -1) {
                let endindex = this.defaultAdress.indexOf("$", beginindex + 1);
                let subDress = this.defaultAdress.substring(beginindex + 1, endindex);
                if (endindex > -1) {
                    if (params && params[subDress]) {
                        this.defaultAdress = this.defaultAdress.replace('$' + subDress + '$', params[subDress]);
                    } else {
                        this.defaultAdress = this.defaultAdress.replace('$' + subDress + '$', '');
                    }
                } else {
                    break;
                }
                beginindex = this.defaultAdress.indexOf("$");
            }

            this.onLoadRight({ href: this.defaultAdress });
        } else {
            this.isCube = false;
            this.mainFrameRefVisible = false;
            this.remarkRefVisible = true;
        }
    }) => {
        this.clear();
        this.init(params, callback);
    }
    @action
    onExpandChange = (expandKeys: string[]) => {
        this.expandKeys = expandKeys;
    }
    @action
    update = (param) => {
        for (let key in param) {
            this[key] = param[key]
        }
    }
    @action
    updateParams = (params: any, forceRefreash = false) => {
        let temp = !_.isEqual(toJS(this.params), params);
        this.params = params;
        if (temp || forceRefreash) {
            this.reloadSearch(params);
        }
    }
    getQuery = (href: string) => {
        const lastofnum = href.lastIndexOf('?');
        href = href.slice(lastofnum);
        const [url, query] = href.split('?');
        const querys = query.split("&");
        const queryObj: any = {};
        _.set(queryObj, url, url)
        querys.map(q => {
            const [name, value] = q.split("=");
            _.set(queryObj, name, value);
        });
        return queryObj;
    }
    @action
    onLoadRight = ({ href }) => {
        this.isCube = false;
        if (href) {
            let url = replaceE8Url(href);
            url = this.checkHref(url);
            if (url.indexOf('?') > -1) {
                this.url = url.split('?').join('?istree=true&_t='+new Date().getTime()+'&');
            } else {
                this.url = `${url}?istree=true&_t=${new Date().getTime()}`;
            }
            if (url.indexOf("/spa/cube/index.html") >= 0) {
                this.isCube = true;
                if (url.indexOf("main/cube/card") >= 0) {
                } else if (url.indexOf("main/cube/search") >= 0) {
                } else if (url.indexOf("main/cube/tree") >= 0) {
                } else if (url.indexOf("main/cube/reply") >= 0) {
                } else {
                    this.isCube = false;
                }
                this.mainFrameRefVisible = false;
            }
            if (!this.isCube) {
                const mainFrame = document.getElementById("cube-tree-mainFrame") as HTMLIFrameElement;
                if (mainFrame) {
                    mainFrame.src = this.url.replace(/&_key=\w{1,10}&/g, '&');//去掉用户配置多加的key
                    this.mainFrameRefVisible = true;
                }
            }
            this.remarkRefVisible = false;
        } else {
            this.remarkRefVisible = true;
            this.mainFrameRefVisible = false;
        }

    }
    @action
    changeLoading = (loading = false) => {
        this.rightLoading = loading;
    }

    @action
    checkHref = (href: string) => {
        let exceptArr = [
            // "/spa/cube/index.html#/main/cube/card",
            "/spa/workflow/index_form.jsp",
            "/spa/document/index.jsp",
            "/spa/hrm/index_mobx.html",
        ];
        for (let index = 0; index < exceptArr.length; index++) {
            const element = exceptArr[index];
            if (href.indexOf(element) > -1) {
                href = href.replace(/(jsp#)|(html#)/g, item => {
                    return item.replace(/(jsp)|(html)/g, type => {
                        return type + `?__random__=${Date.now()}`;
                    });
                });
                return href;
            }
        }

        return href;
    }
}

export default new TreeStore();
